package com.naiterui.ehp.bs.doctor.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.naiterui.ehp.bp.support.utils.JsonMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.naiterui.common.repository.page.CustomizedPageConvertor;
import com.naiterui.common.repository.page.Page;
import com.naiterui.common.repository.page.PageVO;
import com.naiterui.ehp.bp.domain.DoctorCharge;
import com.naiterui.ehp.bp.domain.MessagePushHistory;
import com.naiterui.ehp.bp.domain.MessageTemplate;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.biz.AppJumpProtocol;
import com.naiterui.ehp.bp.utils.lang.ConfigUtil;
import com.naiterui.ehp.bp.utils.notice.AppNoticeUtil;
import com.naiterui.ehp.bp.utils.notice.AppNoticeUtil.DrDynamicInfo;
import com.naiterui.ehp.bp.utils.notice.AppNoticeUtil.NoticeType;
import com.naiterui.ehp.bs.doctor.dao.IMessagePushHistoryDao;
import com.naiterui.ehp.bs.doctor.dao.IMessageTemplateDao;
import com.naiterui.ehp.bs.doctor.repository.IDoctorChargeRepository;
import com.naiterui.ehp.bs.doctor.service.IPAService;
import com.naiterui.ehp.bs.doctor.utils.ImageUrlUtil;
import com.naiterui.ehp.bs.doctor.utils.PropertyValueConstants;
import com.naiterui.ehp.bs.doctor.utils.RedisUtils;
import com.naiterui.ehp.bs.doctor.vo.PAMessageVo;

@Service
public class AdPAServiceImpl implements IPAService {

    private static final Logger LOGGER = LoggerFactory.getLogger(AdPAServiceImpl.class);
    @Autowired
    private IMessagePushHistoryDao messagePushHistoryDao;
    @Autowired
    private IMessageTemplateDao messageTemplateDao;

    @Autowired
    private IDoctorChargeRepository chargeRepository;

    @Override
    public PageVO<PAMessageVo> findPagePaList(Long doctorId, int pageNo, int pageSize, Date createTime) {

        // 保存本次查看时间
        String seeKey = PropertyValueConstants.PA_SEE_CHECK_KEY + doctorId;
        RedisUtils.set(seeKey, System.currentTimeMillis() + "");

        Page<MessagePushHistory> daoPage = messagePushHistoryDao.findPagePaList(doctorId, pageNo, pageSize, createTime);
        List<PAMessageVo> list = new ArrayList<>();
        for (MessagePushHistory h : daoPage.getResult()) {
            PAMessageVo vo = new PAMessageVo();
            vo.setId(h.getId());
            vo.setContent(h.getContent());
            vo.setSysTime(h.getCreatedAt().getTime());
            list.add(vo);
        }
        if (pageNo > daoPage.getPageNo()) {
            return new PageVO<>();
        }
        return CustomizedPageConvertor.buildPageVOWithCustom(pageNo, pageSize, list, (int) daoPage.getTotalCount());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void savePaWithNotice(Long doctorId, String paramValue, int type, AppNoticeUtil.DrDynamicInfo drNoticeInfo) throws BusinessException {
        saveNoticeWithLinkParam(doctorId, paramValue, null, type, drNoticeInfo);
    }

    /**
     * 发送系统消息Notice,简易Notice
     * PAServiceImpl.sendNotice()
     *
     * @param doctorId
     * @param content  通知的内容
     *
     * @return TODO
     *
     * @Author Amber
     * @Date 2017年8月10日
     * @since 1.0.0
     */
    private DrDynamicInfo simpleNotice(Long doctorId, String content) {
        try {
            // 系统消息 notice路径
            String noticePath = ImageUrlUtil.genNoticePath(ConfigUtil.getString("img.notice.dynamic"));
            // 构建notice

            return new DrDynamicInfo(content, System.currentTimeMillis(), AppJumpProtocol.DR_DYNAMIC.parse(), noticePath);
        } catch (Exception e) {
            LOGGER.error("系统消息通知失败，医生id{},通知内容{}", doctorId, content, e);

        }
        return null;
    }

    /**
     * 发送系统消息Notice
     * PAServiceImpl.sendNotice()
     *
     * @param doctorId   非空
     * @param noticeInfo 非空
     *
     * @Author Amber
     * @Date 2017年8月10日
     * @since 1.0.0
     */
    private void sendNotice(Long doctorId, DrDynamicInfo noticeInfo) throws BusinessException {
        if (doctorId == null || noticeInfo == null) {
            LOGGER.error("Notice信息有误，Notice失败。医生id {}", doctorId);
            return;
        }
        // amp服务地址
        String ampHost = ConfigUtil.getString("amp.host.url");
        // 发送系统notice到客户端
        AppNoticeUtil.sendSingleNotice(ampHost, doctorId, NoticeType.DR_DYNAMIC_INFO, noticeInfo);
    }

    private List<String> getTemplateByType(int type) {

        // 从缓存中获取相应类型的消息
        List<String> templateList = new ArrayList<>();
        String cacheKey = getTemplateCacheKeyByType(type);
        Object templateValue = RedisUtils.get(cacheKey);
        if (templateValue != null && templateValue instanceof List) {
            templateList = (List<String>) templateValue;
            return templateList;
        } else {
            // 刷新缓存，再次获取
            findAllTemplate2Cache();
            templateValue = RedisUtils.get(cacheKey);
            if (templateValue != null && templateValue instanceof List) {
                templateList = (List<String>) templateValue;
                return templateList;
            }
        }
        return templateList;
    }

    public void findAllTemplate2Cache() {
        List<MessageTemplate> list = messageTemplateDao.findAllTemplate();
        // 按照类型，存放消息模板
        Map<Integer, List<String>> map = new HashMap<>();
        for (MessageTemplate template : list) {
            int type = template.getType();
            List<String> contentList = map.get(type);
            if (contentList == null) {
                contentList = new ArrayList<>();
                map.put(type, contentList);
            }
            String content = template.getContent();
            LOGGER.info(content);
            contentList.add(content);
        }

        // 迭代key,存放到redis中
        Set<Integer> set = map.keySet();
        for (Integer key : set) {
            List<String> contentList = map.get(key);

            try {
                RedisUtils.set(getTemplateCacheKeyByType(key), contentList);
            } catch (Exception e) {

                LOGGER.info("向redis存放推送消息模板失败key=" + key, e);
            }
        }
    }

    /**
     * 系统通知内容超链接处理
     * PAServiceImpl.replaceByUrl()
     *
     * @param content
     * @param type
     *
     * @return
     *
     * @Author Amber
     * @Date 2017年8月7日
     * @since 1.0.0
     */
    private String replaceByUrl(String content, Integer type, Object... linkParams) {
        try {
            switch (type) {
                case PropertyValueConstants.TEMPLATE_TYPE_REGIST:
                    // 注册通知超链接格式化
                    String authStr = "<a href='" + AppJumpProtocol.DR_AUTH_PAGE.parse() + "'>立即认证</a>";
                    content = content.replaceAll("立即认证", authStr);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_AUTH_APPLY:
                    // 提交认证资料通知超链接格式化
                    String serTel = ConfigUtil.getString("init.server.phone");
                    content = content.replaceAll("客服热线", "<a href='" + AppJumpProtocol.DR_TELL.parse(serTel) + "'>客服热线</a>");
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_AUTH_SUCCESS:
                    // 认证成功通知超链接格式化
                    String authSuccessHref = "<a href='" + AppJumpProtocol.DR_FEES_CONFIG.parse() + "'>点击修改</a>";
                    content = content.replaceAll("点击修改", authSuccessHref);
                    LOGGER.info("消息content={}",content);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_AUTH_FALD:
                    // 认证失败通知超链接格式化
                    String authFailHref = "<a href='" + AppJumpProtocol.DR_AUTH_PAGE.parse() + "'>点击修改</a>";
                    content = content.replaceAll("点击修改", authFailHref);
                    LOGGER.info(content);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_RECORD_SUCCESS:
                    // 备案通过通知超链接格式化
                    /*String acga = "<a href='" + AppJumpProtocol.DR_GDCA_SIGN.parse() + "'>马上设置电子签名</a>";
                    content = content.replace("马上设置电子签名", acga);*/

                    String recordNotice = content + "<a href='" + AppJumpProtocol.DR_FEES_CONFIG.parse() + "'>点击修改</a>";
                    content = recordNotice;

                    LOGGER.info(content);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_RECORD_FAIL:
                    // 备案失败通知超链接格式化
                    String recordFail = "<a href='" + AppJumpProtocol.DR_CENTER.parse() + "'>点击这里请重新提交</a>";
                    content = content.replace("点击这里请重新提交", recordFail);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_RECORD_REQUIRED:
                    // 要求备案通知超链接格式化
                    String recordRequired = "<a href='" + AppJumpProtocol.DR_CENTER.parse() + "'>点击这里请提交互联网医院备案资料</a>";
                    content = content.replace("点击这里请提交互联网医院备案资料", recordRequired);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_PARTBUY:
                case PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_ALLBUY:
                case PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_CANCELBUY:
                    String recomId = "";
                    if (linkParams != null && linkParams.length > 0) {
                        recomId = linkParams[0].toString();
                    }
                    String recomDetailPage = "，<a href='" + AppJumpProtocol.DR_RECOM_DETAIL.parse(recomId) + "'>点击查看详情</a>";
                    content += recomDetailPage;
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_MEDICATION_REMIND:
                    String notifyId = "";
                    if (linkParams != null && linkParams.length > 0) {
                        notifyId = linkParams[0].toString();
                    }
                    String patientListPage = "<a href='" + AppJumpProtocol.DR_MEDICTION_REMIND.parse(notifyId)
                            + "'>点击查看</a><br>注：如果点击无反应请将app升级至最新版本<br>";
                    content += patientListPage;
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_REFERRALNOTICE:
                    String patientName = "";
                    String patientId = null;
                    if (linkParams != null && linkParams.length > 0) {
                        patientName = linkParams[0].toString();
                        patientId = linkParams[1].toString();
                    }
                    String patientHref = "<a href='" + AppJumpProtocol.REFERRAL_REMIND_TO_DOCTOR.parse(patientId) + "'>点击这里与" + patientName
                            + "患者沟通</a>";
                    content += patientHref;
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITER:
                    // 处理逻辑跟TEMPLATE_TYPE_CDSS_NOTIFY_INVITEE一样
                case PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITEE:
                    String link = "";
                    if (linkParams != null && linkParams.length > 0) {
                        link = linkParams[0].toString();
                    }
                    String jump = "<a href='" + AppJumpProtocol.DR_WEB.parse(link) + "'>点击这里</a>";
                    content = content.replace("点击这里", jump);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_CASE_COLLECT_INVITE_NOTIFY:
                    String caseInviteRecomId = "";
                    if (linkParams != null && linkParams.length > 0) {
                        caseInviteRecomId = linkParams[0].toString();
                    }
                    String caseInvitejumpFlag = "<a href='" + AppJumpProtocol.DR_CASE_COLLECT_INVITE.parse(caseInviteRecomId) + "'>点击这里</a>";
                    content = content.replace("点击这里", caseInvitejumpFlag);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_CASE_COLLECT_SUCCESS_NOTIFY:
                    String caseSuccessPointHistoryId = "";
                    if (linkParams != null && linkParams.length > 0) {
                        caseSuccessPointHistoryId = linkParams[0].toString();
                    }
                    String caseSuccessjumpFlag = "<a href='" + AppJumpProtocol.DR_POINT_DETAIL.parse(caseSuccessPointHistoryId) + "'>点击这里</a>";
                    content = content.replace("点击这里", caseSuccessjumpFlag);
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_CONSULT_COMMENT_NOTIFY:
                    String commentId = "";
                    if (linkParams != null && linkParams.length > 0) {
                        commentId = linkParams[0].toString();
                    }
                    String commnentNotice = content + "<a href='" + AppJumpProtocol.DR_CONSULT_COMMENT_NOTICE.parse(commentId) + "'>点击查看详情</a>";
                    content = commnentNotice;
                    break;
                case PropertyValueConstants.TEMPLATE_TYPE_FOLLOW_UP_NOTIFY:
                    Map<String, Object> followMap = new HashMap<>();
                    if (linkParams != null && linkParams.length > 0) {
                        followMap.put("followUpId", linkParams[0].toString());
                        followMap.put("type", linkParams[1].toString());
                    }
                    String followLinkUrl = AppJumpProtocol.DR_FOLLOW_UP_NOTICE.parse(JsonMapper.toJson(followMap));
                    String followUpNotice =
                        content + "<a href='" + followLinkUrl + "'>点击查看详情</a>";
                    content = followUpNotice;
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            LOGGER.error("系统通知超链接处理异常，content：{}, type：{}", content, type);
        }

        return content;
    }

    private String getTemplateCacheKeyByType(Integer type) {
        String cacheKey = PropertyValueConstants.PA_TEMPLATE_KEY + type;
        return cacheKey;
    }

    private List<MessagePushHistory> saveMessage(Long doctorId, Object[] templateParam, String[] linkParam, int type) {
        List<MessagePushHistory> messageList = new ArrayList<>();
        // 从缓存根据消息推送类型获取模板信息
        List<String> tempalteList = getTemplateByType(type);
        if (tempalteList == null || tempalteList.size() <= 0) {
            LOGGER.info("模板信息为空，模板类型type=" + type);
            return messageList;
        }

        for (String temp : tempalteList) {
            String msg = temp;
            // 动态参数格式化
            if (type == PropertyValueConstants.TEMPLATE_TYPE_AUTH_APPLY || type == PropertyValueConstants.TEMPLATE_TYPE_AUTH_FALD
                    || type == PropertyValueConstants.TEMPLATE_TYPE_POINT_FINANCE_SUCCESS
                    || type == PropertyValueConstants.TEMPLATE_TYPE_POINT_CS_FALD || type == PropertyValueConstants.TEMPLATE_TYPE_POINT_FINANCE_FALD
                    || type == PropertyValueConstants.TEMPLATE_TYPE_ACOUNT_MODIFY || type == PropertyValueConstants.TEMPLATE_TYPE_RECORD_FAIL
                    || type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_PARTBUY
                    || type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_ALLBUY || type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_CANCELBUY
                    || type == PropertyValueConstants.TEMPLATE_TYPE_MEDICATION_REMIND
                    || type == PropertyValueConstants.TEMPLATE_TYPE_REFERRALNOTICE || type == PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITER
                    || type == PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITER_FOREVER
                    || type == PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITEE
                    || type == PropertyValueConstants.TEMPLATE_TYPE_CASE_COLLECT_INVITE_NOTIFY
                    || type == PropertyValueConstants.TEMPLATE_TYPE_CASE_COLLECT_SUCCESS_NOTIFY
                || type == PropertyValueConstants.TEMPLATE_TYPE_CONSULT_COMMENT_NOTIFY
                || type == PropertyValueConstants.TEMPLATE_TYPE_FOLLOW_UP_NOTIFY) {
                // 使用paramValue替换
                msg = String.format(temp, templateParam);
            }
            // 认证成功特殊处理
            if (PropertyValueConstants.TEMPLATE_TYPE_AUTH_SUCCESS==type){
                msg = this.formatAuthSuccess(msg,doctorId);
            }
            // 处理内容超链接
            msg = replaceByUrl(msg, type, linkParam);
            MessagePushHistory history = new MessagePushHistory();

            history.setContent(msg);
            Date date = new Date();
            //前端比较精确到ms，数据库精确到s，大于500ms的时间数据库会四舍五入
            history.setCreatedAt(new Date(date.getTime() / 1000 * 1000));
            history.setDoctorId(doctorId);
            messagePushHistoryDao.save(history);
            messageList.add(history);
        }
        return messageList;
    }


    @Override
    public String getContentByType(int type, Object... params) {
        // 从缓存根据消息推送类型获取模板信息
        List<String> tempalteList = getTemplateByType(type);
        if (tempalteList == null || tempalteList.size() <= 0) {
            LOGGER.info("模板信息为空，模板类型type=" + type);
            return "";
        }
        String msg = tempalteList.get(0);
        // 动态参数格式化
        if (type == PropertyValueConstants.TEMPLATE_TYPE_AUTH_APPLY || type == PropertyValueConstants.TEMPLATE_TYPE_AUTH_FALD
                || type == PropertyValueConstants.TEMPLATE_TYPE_POINT_FINANCE_SUCCESS || type == PropertyValueConstants.TEMPLATE_TYPE_POINT_CS_FALD
                || type == PropertyValueConstants.TEMPLATE_TYPE_POINT_FINANCE_FALD || type == PropertyValueConstants.TEMPLATE_TYPE_ACOUNT_MODIFY
                || type == PropertyValueConstants.TEMPLATE_TYPE_RECORD_FAIL || type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_PARTBUY
                || type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_ALLBUY || type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_CANCELBUY
                || type == PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITER
                || type == PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITER_FOREVER
                || type == PropertyValueConstants.TEMPLATE_TYPE_CDSS_NOTIFY_INVITEE) {
            // 使用paramValue替换
            msg = String.format(msg, params);
        }
        return msg;
    }

    /**
     * 发送站内通知，带跳转参数
     *
     * @param doctorId
     * @param templateParam
     * @param linkParam
     * @param type
     * @param drNoticeInfo
     *
     * @throws BusinessException
     * @Date 2018年3月27日
     * @since 2.16
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveNoticeWithLinkParam(Long doctorId, String templateParam, String linkParam, int type, DrDynamicInfo drNoticeInfo)
            throws BusinessException {
        saveNoticeWithLinkParam(doctorId, templateParam == null ? null : new String[]{templateParam},
                                     linkParam == null ? null : new String[]{linkParam}, type, drNoticeInfo);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveNoticeWithLinkParam(Long doctorId, String[] templateParam, String[] linkParam, int type, DrDynamicInfo drNoticeInfo)
            throws BusinessException {
        // 原有逻辑认为每个type可能会有多条模板，有待商榷TODO:，逻辑暂时保持
        List<MessagePushHistory> messages = saveMessage(doctorId, templateParam, linkParam, type);

        if (drNoticeInfo == null) {
            // 如果没有自定义通知，默认按照动态内容发送简单Notice
            for (MessagePushHistory message : messages) {
                drNoticeInfo = simpleNotice(doctorId, message.getContent());
                sendNotice(doctorId, drNoticeInfo);
            }
        } else {
            //阳光化医生全部购买和取消购买会发短系统通知
            if (type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_ALLBUY || type == PropertyValueConstants.TEMPLATE_TYPE_RECOMMEND_CANCELBUY) {
                drNoticeInfo = new AppNoticeUtil.DrDynamicInfo(drNoticeInfo.getContent(), System.currentTimeMillis(), AppJumpProtocol.DR_DYNAMIC
                        .parse(),
                                                               drNoticeInfo.getHeadImg(), drNoticeInfo.getStatus(), drNoticeInfo.getRecordStatus());
            } else if (messages.size() > 0) {
                String msg = messages.get(0).getContent();
                if (StringUtils.isNotBlank(msg)) {
                    drNoticeInfo = new AppNoticeUtil.DrDynamicInfo(msg, System.currentTimeMillis(), AppJumpProtocol.DR_DYNAMIC.parse(),
                                                                   drNoticeInfo.getHeadImg(), drNoticeInfo.getStatus(),
                                                                   drNoticeInfo.getRecordStatus());
                }
            }
            // 按照自定义通知发动sNotice
            sendNotice(doctorId, drNoticeInfo);
        }
    }

    @Override
    public String formatAuthSuccess(String msg,long doctorId) {
        String consultChargeText = "0";
        String videoChargeText = "0";
        DoctorCharge textCharge = chargeRepository.findFirstByDoctorIdAndChargeType(doctorId, 1);
        DoctorCharge videoCharge = chargeRepository.findFirstByDoctorIdAndChargeType(doctorId, 2);
        if (textCharge != null){
            consultChargeText = String.valueOf(textCharge.getCharge()/100);
        }
        if (videoCharge != null){
            videoChargeText = String.valueOf(videoCharge.getCharge()/100);
        }
        msg = String.format(msg, "￥"+consultChargeText+"/次", "￥"+videoChargeText+"/15分钟");

        return msg;
    }

}
